package wili.attrMapping._user.b1.exp;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import wili.attrMapping._user.b1.B1com;
import wili.c.Str9a;
import wili.c.Str9a.IndMap;
import wili.logic.ToIndentLogicExp;

/**
 *
 */
public class AndOrExp2 {
	public final String expSt;
	final String andOp = "&&", orOp = "||";
	public AndOrNode2 rootNode;
	public final boolean useSexp;

	public String toString() {
		return rootNode.toString();
	}

	@SuppressWarnings("rawtypes")
	public Boolean isTrue(Map cont) {
		return rootNode.isTrue(cont);
	}

	public static class EquivalentRet {
		public Map<String, Object> map;
		public String msg = "";

		public String toString() {
			if (map == null) {
				return "等价性未知.";
			} else if (map.isEmpty()) {
				String ret = "两式等价.";
				if (!msg.isEmpty())
					ret = ret + "\n" + msg;
				return ret;
			} else {
				String ret = "两式不等价.";
				if (!msg.isEmpty())
					ret = ret + "\n" + msg;
				return ret;
			}
		}

		@SuppressWarnings("unchecked")
		public EquivalentRet() {
			map = Collections.EMPTY_MAP;
		}

		public EquivalentRet(Map<String, Object> map, String msg) {
			this.map = map;
			this.msg = msg;
		}
	}

	public void setRootNode(AndOrNode2 root) {
		this.rootNode = root;
	}

	public static EquivalentRet isEquivalentLogicExp(String exp1, String exp2) {
		// ToIndentLogicExp obj = new ToIndentLogicExp(exp1.toString());
		AndOrExp2 root1 = AndOrExp2.newInst(-1, exp1);
		root1.print(1);
		// ToIndentLogicExp obj2 = new ToIndentLogicExp(exp2.toString());
		AndOrExp2 root2 = AndOrExp2.newInst(-1, exp2);
		List<Varb1> vars = new ArrayList<>();
		root1.rootNode.findVarList("", vars);
		root2.rootNode.findVarList("", vars);
		Set<String> varSet = new HashSet<>();
		varSet.addAll(vars.stream().map(e -> e.name).collect(Collectors.toSet()));
		varSet.addAll(vars.stream().map(e -> e.name).collect(Collectors.toSet()));
		//
		File file = new File("c:/bearJ/awilly/webclientOptValues.txt");
		ValueMapIterator valueMapIt = new ValueMapIterator(varSet, file);
		// String msg = Misc9a.strOfMap(valueMapIt.optValuesMap, "\n\t");
		int[] trueFalseTimes = { 0, 0 };
		while (valueMapIt.hasNext()) {
			Map<String, Object> map = valueMapIt.next();
			for (Varb1 va : vars)
				va.setValue(map);
			boolean v1 = root1.rootNode.isTrue(null);
			boolean v2 = root2.rootNode.isTrue(null);
			if (v1 != v2)
				return new EquivalentRet(map,
						"左" + (v1 ? "真" : "假") + "右" + (v2 ? "真" : "假") + ", 当变量取值" + map + " 时。");
			trueFalseTimes[v1 ? 0 : 1]++;
		}
		return new EquivalentRet();// has same value.
	}

	IndMap lrIndMap;

	private AndOrExp2(int useSexp, String expSt) {
		// expSt = "!" + expSt;
		this.useSexp = useSexp == 1;
		expSt = B1com.standarlizeExpOp(expSt);
		this.expSt = expSt;
		this.lrIndMap = Str9a.readBracketIndMap(expSt);
		this.rootNode = new AndOrNode2(expSt, 0, expSt.length(), this);
	}

	public static AndOrExp2 newInst(int useSexp, String expSt) {
		if ("asdf".isEmpty()) {
			ToIndentLogicExp obj = new ToIndentLogicExp(expSt);
			return null;// new AndOrExp(obj.root);
		}
		AndOrExp2 ret = new AndOrExp2(useSexp, expSt);
		return ret;
	}

	public void sortSonsBySt() {
		if (rootNode == null)
			return;
		rootNode.sortSonsBySt(9);
	}

	public void print(int use) {
		if (use < 0)
			return;
		rootNode.print("");
	}
}
